﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace Glossary
{
    static public class Input
    {
        /// <summary>
        /// Saves a list containing word objects to a file. The standard format language id on first line and foreign;swedish format follows.
        /// </summary>
        /// <param name="path">path to where it will be saved</param>
        /// <param name="WordList">words that will be saved</param>
        /// <param name="lang">what language it's in</param>
        static public void SaveToWordFile(string path, List<Word> WordList, Languages lang)
        {
            // Input for New Words. Use EXEC AddNewWordProc @foreignword, @swedishword, @language, [@description]
            // metod för skapa prov och lägga till glosa ä nu olika metoder
            using (StreamWriter sw = new StreamWriter(path, false))
            {
                sw.WriteLine((int)lang);
                for (int i = 0; i < WordList.Count; i++)
                    sw.WriteLine(String.Format("{0};{1}", WordList[i].Foreign, WordList[i].Swedish));

            }
        }

        /// <summary>
        /// Student save of finished exam. params parameter is non optional.
        /// </summary>
        /// <param name="path">saved to here</param>
        /// <param name="wordList">finished exam</param>
        /// <param name="lang">language exam is in</param>
        /// <param name="person">person information, shall always be printed non optional</param>
        static public void SaveUncorrectedExam(List<Word> wordList, Languages lang, params string[] person)
        {
            if (person.Length != 5)
                throw new MissingInformationException("Personal information must be enter into the saved exam.");

            string path = Directory.GetCurrentDirectory() + String.Format("\\UncorrectedExams\\");
            if (!Directory.Exists(path))
                Directory.CreateDirectory(path);
            path += String.Format("{0}-{1}-{2}-{3}_{4}_uncorrectedExam.txt",
                DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, person[0], person[1]);

            using (StreamWriter sw = new StreamWriter(path, false))
            {
                StringBuilder sb = new StringBuilder();
                sb.Append((int)lang);
                for (int i = 0; i < person.Length; i++)
                    sb.Append(String.Format(";{0}", person[i]));

                sw.WriteLine(sb.ToString());
                for (int i = 0; i < wordList.Count; i++)
                    sw.WriteLine(String.Format("{0};{1};{2}", wordList[i].Foreign, wordList[i].Swedish, wordList[i].Answer));
            }
        }

        /// <summary>
        /// For the teacher, when saving an corrected exam.
        /// </summary>
        /// <param name="path">where file is saved</param>
        /// <param name="exam">exam that will be corrected</param>
        /// <param name="firstLine">person information</param>
        static internal void SaveCorrectedExam(List<Word> exam, string[] firstLine)
        {
            if (firstLine.Length < 5)
                throw new MissingInformationException("Personal information must be enter into the saving of a corrected exam.");

            string path = Directory.GetCurrentDirectory() + String.Format("\\CorrectedExams\\");
            if (!Directory.Exists(path))
                Directory.CreateDirectory(path);
            path += String.Format("{0}-{1}-{2}-{3}_{4}_correctedExam.txt", DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, firstLine[1], firstLine[2]);

            using (StreamWriter sw = new StreamWriter(path, false))
            {
                StringBuilder sb = new StringBuilder();
                sb.Append(firstLine[0]);
                for (int i = 1; i < firstLine.Length; i++)
                    sb.Append(String.Format(";{0}", firstLine[i]));

                int amountOfCorrectResults = 0;
                foreach (Word word in exam)
                    amountOfCorrectResults += (word.Correct) ? 1 : 0;
                sb.Append(String.Format(";{0}", amountOfCorrectResults));
                sb.Append(String.Format(";{0}", exam.Count));

                sw.WriteLine(sb.ToString());
                for (int i = 0; i < exam.Count; i++)
                    sw.WriteLine(String.Format("{0};{1};{2};{3}", exam[i].Foreign,
                        exam[i].Swedish, exam[i].Answer, exam[i].Correct.ToString()));
                
            }
            Input.CreateHtmlDoc(path);
        }

        /// <summary>
        /// Used by teacher to correct and exam.
        /// </summary>
        /// <param name="path"></param>
        /// <param name="cs"></param>
        static public void CorrectExam(string path, CaseSensitive cs)
        {
            Languages fileLanguage = Output.GetFileLanguage(path);
            string[] information = new string[5];
            List<Word> exam = Output.ReadUncorrectedExam(path, ref information);

            string currentDir = Directory.GetCurrentDirectory();

            foreach (Word w in exam)
                w.CheckAnswer(cs);

           Input.SaveCorrectedExam(exam, information);
        }

        /// <summary>
        /// Adds a new word at the end of an existing dictionary.
        /// </summary>
        /// <param name="foreign">The foreign word</param>
        /// <param name="swedish"> The swedish word</param>
        /// <param name="lang">What language it is in</param>
        static public void AddNewWord(string foreign, string swedish, Languages lang)
        {
            //Add to check that it doesnt add dups.... what about Orange? Apelsin lr Orange?
            foreign = FormatWord(foreign);
            swedish = FormatWord(swedish);

            Word w = new Word(foreign, swedish);
            string dictionaryPath = Directory.GetCurrentDirectory() + "\\Dictionaries\\";
            if (!Directory.Exists(dictionaryPath))
                Directory.CreateDirectory(dictionaryPath);

            Languages languages;

            DirectoryInfo di = new DirectoryInfo(dictionaryPath);
            FileInfo[] Files = di.GetFiles("*.txt");

            foreach (FileInfo file in Files)
            {
                using (StreamReader sr = new StreamReader(dictionaryPath + file.Name))
                {
                    string firstLine = sr.ReadLine();
                    int langId = 0;
                    try
                    {
                        langId = int.Parse(firstLine);
                    }
                    catch (FormatException e)
                    {
                        throw new InvalidLanguageException(String.Format("This is not a valid language, in Enum.Languages", e.Message), e);
                    }
                    languages = (Languages)langId;
                }

                if (lang == languages)
                {
                    using (StreamWriter sw = new StreamWriter(dictionaryPath + file.Name, true))
                    {
                        sw.WriteLine(w.Foreign + ";" + w.Swedish);
                    }
                }
            }
        }

        /// <summary>
        /// Creates and exam from one of the dictionary files.
        /// </summary>
        /// <param name="lang">What languages the exam is in</param>
        /// <param name="numb">How many words in the exam</param>
        static public void CreateExamFile(Languages lang, Numbers numb)
        {
            string dictionaryPath = Directory.GetCurrentDirectory() + String.Format("\\Dictionaries\\");
            if (!Directory.Exists(dictionaryPath))
                Directory.CreateDirectory(dictionaryPath);
            dictionaryPath += String.Format("{0}.txt", lang.ToString());
            if (!File.Exists(dictionaryPath))
                throw new FileNotFoundException("The dictionary file is missing.");

            List<Word> library = Output.ReadFromFile(dictionaryPath);
            List<Word> exam = new List<Word>();
            Random rnd = new Random();

            exam = library.OrderBy(x => rnd.Next()).Take((int)numb).ToList();

            string savePath = Directory.GetCurrentDirectory() + "\\Exams\\";
            if (!Directory.Exists(savePath))
                Directory.CreateDirectory(savePath);
            savePath += String.Format("exam_{0}-{1}-{2}-{3}.txt", lang.ToString(), DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day);

            SaveToWordFile(savePath, exam, lang);
        }

        /// <summary>
        /// Conforms a word to meet the standard of the glossary files.
        /// </summary>
        /// <param name="word"></param>
        /// <returns></returns>
        internal static string FormatWord(string word)
        {
            foreach (char item in word)
                if (!char.IsLetter(item))
                    throw new SignException("Only letter are allowed in the word.");

            StringBuilder sb = new StringBuilder();
            word = word.ToLower();
            sb.Append(Char.ToUpper(word[0]));
            for (int i = 1; i < word.Length; i++)
                sb.Append(word[i]);

            return sb.ToString();
        }

        /// <summary>
        /// Creates an html file from a corrected .txt file exam
        /// </summary>
        /// <param name="path"></param>
        static private void CreateHtmlDoc(string path)
        {
            string[] textFileToArray;
            string textFromStreamReader;
            StringBuilder htmlDoc = new StringBuilder();

            htmlDoc.AppendLine("<html>").AppendLine("<body>").AppendLine("<head>").AppendLine("<meta charset=\"UTF-8\">").AppendLine("</head>");
            StreamReader streamReader = new StreamReader(path, Encoding.UTF8);

            textFromStreamReader = streamReader.ReadLine();
            textFileToArray = textFromStreamReader.Split(';');

            string savePath = Directory.GetCurrentDirectory() + "\\Html\\";
            if (!Directory.Exists(savePath))
                Directory.CreateDirectory(savePath);
            savePath+= String.Format("{0}-{1}-{2}-{3}_{4}_correctedExam.html", DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, textFileToArray[1], textFileToArray[2]);

            htmlDoc.AppendLine("<p>" + textFileToArray[1] + " " + textFileToArray[2] + "</p>").AppendLine("<p>" + textFileToArray[3] + "</p>").AppendLine("<p>" + textFileToArray[4] + " " + textFileToArray[5] + "</p>").AppendLine("<p>" + textFileToArray[6] + "/" + textFileToArray[7] + "</p>");
            htmlDoc.AppendLine("<table border=\"2\" width =\"400\">").AppendLine("<tr><th>Glosa</th><th>Svenska</th><th>Ditt svar</th><th>Resultat</th></tr>");

            while ((textFromStreamReader = streamReader.ReadLine()) != null)
            {                
                textFileToArray = textFromStreamReader.Split(';');
                htmlDoc.AppendLine("<tr><td>" + textFileToArray[0] + "</td><td>" + textFileToArray[1] + "</td><td>" + textFileToArray[2] + "</td><td>" + textFileToArray[3] + "</td></tr>");
            }
            streamReader.Close();
            htmlDoc.AppendLine("</table>").AppendLine("</body>").AppendLine("</html>");

            using (StreamWriter WriteHtmlDoc = new StreamWriter(savePath, false, Encoding.UTF8))
            {
                WriteHtmlDoc.WriteLine(htmlDoc.ToString());
            }
        }
    }
}
